home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-06-07 | 37.2 KB | 1,063 lines | [TEXT/ALFA] |
-
-
-
-
-
-
-
-
-
-
-
-
-
- FRACTAL LAB KIT
-
- IFS mappings module
-
-
- Ronald T. Kneusel
- May 25, 1993
- version 1.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Table of Contents
-
-
-
- I. Introduction
- What is this all about?................................. 3
- Fractals and IFS (Iterated Function System)............. 5
- Getting started......................................... 10
-
-
- II. Tutorial
- A sample session........................................ 11
- Using preset fractal maps............................... 12
- Using basic commands.................................... 12
- Using the FindMap command, an example.................. 15
-
-
- III. Advanced features
- A very brief introduction to programming in Forth....... 16
- An example : the Sierpinski Triangle.................. 19
- Basic Forth words....................................... 21
-
-
- IV. Reference
-
- Commands................................................ 22
- Primitive words......................................... 25
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Introduction
-
- What is this all about?
-
- The fractal lab kit is a command driven system for generating and
- investigating fractal images. It is written using Chris Heilman's Pocket
- Forth , a small Forth interpreter for the Macintosh. Pocket Forth is
- available via anonymous FTP from archive.umich.edu in the directory
- /mac/development/languages/.
- The kit consists of a set of Forth words that allow the user to easily
- create fractals based on IFS mappings. Because of it's small size and
- generality, it should run on virtually all Macintosh computers. By
- entering simple commands the user can define maps, draw the resultant
- fractals in a variety of colors, show the orientation of the mappings,
- measure positions within the image, and zoom in to view details. Fractals
- using up to 12 maps can be generated.
-
- Why not create a standard Macintosh application for all of this?
-
- I used Forth for two reasons. First, I am still learning the language
- and thought that this would be a good project towards that end.
- Secondly, I have used several fractal programs in the past and while they
- are excellent at what they do, they are rigid and inflexible. Creating a
- system like this in Forth seemed ideal. Forth is fast and highly
- interactive. It is also small and very easily extended. Not only does
- the user have all the fractal commands, but they also have all of Forth
- still at their disposal. A little programming can quickly extend the
- existing capabilities. Pocket Forth was my choice for several reasons,
- primarily, it is free and can be freely distributed, as well as supporting
- floating point numbers to make life easier.
-
-
-
-
-
-
-
-
-
-
- Fractal Lab Kit is freeware, if you use it and have any suggestions or
- comments please let me know at the addresses below. I have plans for
- additional 'modules' for investigating Mandelbrot and Julia sets, biomorph
- images, and chaos in one and two dimensions. Your feedback will encourage
- me to continue. Even if you have no specific comment, let me know where
- you are so I can follow the program. I prefer postcards, but email is
- good too.
-
- Ron Kneusel
- 507 S. 92nd St.
- Milwaukee, WI 53214
- USA
-
- kneusel@msupa.pa.msu.edu
- or
- rtk@herman.gem.valpo.edu
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Fractals and IFS: an overview
-
- A fractal is a geometric object with a non-integer dimension. We are
- used to thinking in terms of Euclidean geometry, that is, in terms of
- points, lines, areas (surfaces), and volumes (solids). Fractals do not
- easily fit in such a framework and are difficult to comprehend (at least
- for me). Common geometrical objects have integer dimensions:
-
- Object Dimension
- ------ ----------
- point 0 (no length or width or depth)
- line 1 (length only, no width or depth)
- plane 2 (length and width)
- solid 3 (length, width and depth)
-
- but fractals have non-integer dimensions, like 0.63... etc. How can this
- be you say? Let's look at the simplest fractal of them all: the Cantor set.
-
- To create the Cantor set imagine a line of length 1. Now, remove the
- middle third of that line. Remove the middle third of the two remaining
- lines. Continue removing the middle third an infinite number of times.
- When you are finished the object you will be left with is a fractal with a
- dimension that is not 0 (it's not a point) but is less than 1 (a line from
- 0 to 1 would contain all points, clearly a cantor set does not) and it can
- be shown that the final dimension is ln2/ln3 = 0.6309297536.....
-
- •••••• Begin Aside: Derivation of the Cantor Set dimension
-
- One possible definition of dimension, the self-similar dimension, is the
- ratio of the natural log of the number of intervals N (in 1-d) of length ß
- needed to completely cover the set to the natural log of the reciprocal of
- ß, taken in the limit that ß-->0. In the case of the Cantor set ß=(1/3)^n
- where n is the "level" of the set. (Check: the second level has two
- sections of length 1/3 while the next level has four sections of length
- 1/9 = (1/3)^2) So the condition ß-->0 becomes n-->∞ . Also, for the
- Cantor set the number of intervals to cover the set at the level n is
- N=2^n . (Check: at the second level there are 2^1 = 2 intervals, at the
- third level there are 2^2=4 intervals and so on.) So we write:
-
- lim lim
- D = n-->∞ ln N / ln (1/ß) = n-->∞ ln (2^n) / ln ( 1/(1/3)^n)
-
- lim
- D = n-->∞ n ln 2 / n ln 3 = ln2 / ln3 = 0.6309297536.....
-
- •••••• End Aside
-
- The Cantor set, like other purely mathematical fractals, is completely
- self-similar. That is, it looks identical on different scales (actually
- it is independent of scale). Take a piece of paper (you do have scrap
- paper near the computer; don't you?) and draw the first few lines of the
- Cantor set, one below the other:
-
- -------------------------
- -------- ---------
- --- --- --- ---
- etc.
-
- (Yours will undoubtedly look better than mine)
-
- If you look at what you have just drawn you will notice that if you
- magnify a lower level it will look like one above it, the entire set is
- made up of an infinite number of copies of itself. (Infinity shows up
- frequently when talking about fractals) As this is a one dimensional
- fractal it is not terribly interesting; the program draws two dimensional
- fractals where life is a little less boring.
-
- They are definitely odd, but fractals do turn up in many places in nature,
- the nautilus shell (see the SPIRAL), your lungs and circulatory system
- (see the TREE), etc. Some people even think that the distribution of
- matter in the universe is a fractal.
-
-
-
-
-
-
- What about fractals and chaos?
-
- Fractals are often mentioned in connection with chaotic behavior of
- dynamical systems. The link comes from the fact that the final attractor
- (a strange attractor) of a dissipative dynamical system is a fractal
- object. If you want to talk more about this, contact me at the above
- address.
-
-
-
- What is IFS?
-
- IFS (Iterated Function System) is the means by which the program
- generates images. It was developed by Michael Barnsley. IFS involves
- defining a number of maps that in some way determine what the final
- product will look like (more on that later). An initial point is chosen
- (the origin is nice) and iterated (i.e. put it in - get something out -
- put that something back in, etc.) . These are maps in the mathematical
- sense - roughly, a way of transforming a collection of points into another
- space or back into its own space as is the case here. The map used for
- each iteration is chosen at random based on the assigned probability, the
- higher the probability the more likely that map is chosen. After each
- iteration the resulting point is plotted. As this process is continued
- the fractal image is built. Changing the probability of a map can
- dramatically affect the resulting image, so it might take a bit to get the
- picture "just right". It should be noted that the IFS algorithm is the
- heart of new data compression techniques that can achieve compression
- ratios of up to 30:1.
-
- In mathematical terms, a 2 dimensional map can be most easily represented
- in matrix form. A matrix is similar to the two dimensional arrays used in
- many programming languages. If we have a starting point (x,y) and we want
- to find the transformed coordinates, (x',y'), we can write the
- transformation in this way:
-
- |x'| |a b| |x| |e|
- |y'| = |c d| |y| + |f|
-
- This is equivalent to writing two equations:
-
- x' = a*x + b*y + e
- y' = c*x + d*y + f
-
- The 2x2 matrix controls the reorientation of the initial coordinate system
- while the vector (e f) is an offset to a new origin point for the map.
-
- Finding the "magic" numbers for an IFS transformation
-
-
- By way of example, I will show how to find the matrix values that
- generate what has become known as the Mandelbrot Dragon. While the dragon
- is usually generated according to a prescription (like the Cantor set
- above) it can also be found using two mappings (i.e. two matrices).
- Recalling that a fractal is made up of an infinite number of copies of
- itself, we need only specify the "first" copy and the IFS algorithm will
- fill in the rest. Therefore, imagine a square from 0 to 1, this is the
- starting point as it were. We must transform the points from this square
- into a different square (or squares), where the number of transformations
- equals the number of "parts" that the fractal is made up of. The dragon
- is made up of two parts: a contracted 45 degree rotation of the coordinate
- axes and a contracted -45 degree rotation (with a flip). Perhaps the best
- way to imagine this is to picture an arrow: ____________\_ from 0 to
- 1, the head of the arrow is only a half head so we can see if there is a
- flip as well as a rotation and translation. After some thought we realize
- that we need something like the following to generate the dragon: Again
- take a piece of paper and draw a 2 inch arrow as above, the head of the
- arrow is on the right and the barb is pointing north. Now, draw another
- arrow from the left edge of the first going at a 45 degree angle until it
- intersects an imaginary line running north to south that passes through
- the midpoint of the first line. Draw the barb of this arrow on the left
- side of the right endpoint of this line. Finally, complete the triangle
- and draw the barb of this arrow on the left side and touching the head of
- the second arrow. When you are finished you will have something like
- this:
-
-
- ( see the MacPaint file 'Dragon Picture' )
-
-
-
-
- where the directions of the arrow heads are crudely indicated. Finally,
- complete each of the three squares determined by the arrows as one edge.
-
- Now comes the fun part, how do we change the drawing into the numbers
- for the maps? To find the maps we need to solve, for each map, two
- systems of three linear equations since there are six numbers to find. To
- write the six equations we must know where at least three points of the
- original square (the one from 0 to 1) map to in the new maps. This is
- where the arrow head directions become important. The arrow determines
- two points for us, the head and the tail, while the last point can be
- either of the two corners of the original square and where they map to in
- the final square. So, to this end, label the tail and head of the first
- arrow drawn (a1,a2) and (b1,b2) respectively, and label the corner of the
- square above (a1,a2) as (c1,c2). These are the original three points, now
- label the corresponding points in the second square (the one at a positive
- 45 degree angle to the first) as (A1,A2) for the tail (in this case they
- are the same point) and (B1,B2) for the head. Label the farthest left
- corner of the square (C1,C2).
-
- Once this is done, we can write the following six equations to determine
- the first map:
-
- a1*a + a2*b + e = A1
- b1*a + b2*b + e = B1
- c1*a + c2*b + e = C1
-
- and
-
- a1*c + a2*d + f = A2
- b1*c + b2*d + f = B2
- c1*c + c2*d + f = C2
-
- In order to get actual numbers, we need to impose a coordinate system.
- Draw an x and y axis where the first arrow goes from 0 to 1 on the x axis
- and left edge of the first square goes from 0 to 1 on the y axis. In this
- coordinate system, (a1,a2)=(0,0); (b1,b2)=(1,0); (c1,c2)=(0,1) and the
- points for the first map are (A1,A2)=(0,0); (B1,B2)=(0.5,0.5);
- (C1,C2)= (-0.5,0.5).
- The values for the matrix and vector are found by solving the two
- systems. Cramer's Rule allows the solutions to be written as:
-
-
-
- |A1 a2 1| |a1 A1 1| |a1 a2 A1|
- |B1 b2 1| |b1 B1 1| |b1 b2 B1|
- |C1 c2 1| |c1 C1 1| |c1 c2 C1|
- a = --------- b = --------- e = ----------
- |a1 a2 1| |a1 a2 1| |a1 a2 1 |
- |b1 b2 1| |b1 b2 1| |b1 b2 1 |
- |c1 c2 1| |c1 c2 1| |c1 c2 1 |
-
-
- Where the vertical lines represent the determinant (not the matrix as I
- have been using them for previously) and with a corresponding set for the
- c, d, and f values. With these we find that the first transformation is:
-
- |x'| |0.5 -0.5| |x| |0|
- |y'| = |0.5 0.5| |y| + |0|
-
- and applying the above to the second map gives:
-
- |x'| |-0.5 -0.5| |x| |1|
- |y'| = | 0.5 -0.5| |y| + |0|
-
- (I will leave the actual solution as an exercise.....)
-
- The last thing to consider is what sort of probability we want to assign
- to each of these maps. Since there is no reason to favor one map to
- another we can in this case get away with a probability of 0.5 for each
- (remember, probabilities should add to 1). This is not always the case,
- though.
- There are many good books on fractals and chaos at all levels, check the
- local book store or library. The book "Chaos: The Making of a New
- Science" by John Gleick is a good place to start, though it is lean on the
- technical aspects.
-
- Getting Started
- The IFS module includes a few different files. Double click the file
- Fractal Lab Kit to get things going. It contains the core IFS words.
- The file IFS-Maps contains about a dozen predefined fractal maps that will
- illustrate much of the versatility that can be obtained. (Thanks to Dr.
- Dale Snider, UW-Milwaukee Dept. of Physics, for the maps). Use Open
- under the File menu to load the maps. Enter the command PRESET to choose
- a map.
- The commands you enter are really just Forth words. In fact, you are
- really using Pocket Forth with the IFS words already defined, however,
- you need not be familiar with Forth to use the program.
-
- Tutorial
-
-
- A Sample Session
-
- In this sample session and what follows, things the user types are
- indicated in bold while the computer's response is in plain text.
-
- <after double-clicking the Fractal Lab Kit icon...>
- ok _open <return>
- <choose the IFS-Maps file from the standard Mac open dialog>
- ok _fern green color on outlines draw
- <program loads the maps for the fern, draws the outlines of the maps,
- waits for a keypress, and draws the fern in green until the user presses a
- key>
- ok _mouse
- <program shows the true coordinates of the mouse pointer until the user
- presses a key>
- ok _settings
- Current plot origin ( 0.00000 , 0.00000 )
- Current screen origin ( 100 , 330 )
- Current x & y scale is 1.0000 : 1.0000
- Axes are currently OFF
- Draw Outlines is currently ON
- Current number of maps = 5
- ok _off outlines 0.178 0.034 origin .25 range cdraw
- <program zooms in to the second leaflet and generates a magnified image
- using a different color for each map until a keypress>
- ok _bye
- <program exits>
-
-
-
-
-
-
-
-
-
-
- Using the Preset Fractal Maps
-
-
- The file IFS-Maps contains code for about a dozen fractals. Use the
- word open or Open from the File menu to load the file. The command preset
- will bring a menu allowing the user to choose a particular fractal. Once
- the maps are loaded, the fractal can be generated by typing draw. All of
- the preset fractals should appear well centered on the screen, though to
- see all of the tree enter 250 330 screen draw to adjust the screen origin
- so that the entire image will fit, then enter reset to restore the default
- settings.
- At present, there is no way to store or print the images other than the
- open-apple-shift-3 command. They can then be loaded into TeachText and
- from there to any paint type program.
-
-
- Basic Commands
-
-
- A list of the basic, and most interactive, commands are presented along
- with an example of their use. These are the minimum commands necessary to
- use the program:
-
- draw
- Draw a fractal based on the current maps. Press a key to stop.
- E.g. green color fern draw
-
- cdraw
- Except for plotting each map in a different color, it is the same as
- draw.
- E.g. spiral cdraw
-
- <n> edit
- Edit the n-th map. Enter a new value or press return to leave the
- existing value as is.
- E.g. 2 edit
- a = 0.5 ?-0.5 (new value)
- b = -0.5 ?<return> etc.
-
- zero-maps
- Erase all twelve maps.
- E.g. zero-maps
-
- <color.name> color
- Set the current drawing color to the color named. Valid colors are
- black, wite, red, green, blue, yellow, cyan, magenta
- E.g. magenta color
-
- <n> maps
- Set the number of maps to use to <n>.
- E.g. 4 maps
-
- <x> <y> origin
- Set the origin to (x,y). X and Y are floating point numbers.
- E.g. -0.354 .789 origin
-
- <u> <v> screen
- Set the screen origin to (u,v) (pixels).
- E.g. 120 220 screen
-
- <r> range
- Set the range to <r> (floating point). The viewing window is a
- square with the lower left corner as the origin and side length
- as range.
- E.g. 0.5 range
-
- <x> <y> scale
- Set the x-axis and y-axis scales to the floating point values given.
- The default scale is 1.0 for a full screen image. Changing the scale
- to a value less than one shrinks the image, greater than one expands
- the image.
- E.g. 2.0 2.0 scale
-
- mouse
- When issued, mouse will translate the position of the pointer into
- an x,y coordinate allowing the user to 'see' where certain parts of
- the image are. Clicking the mouse button between two points will
- measure the distance between them. Press a key to exit.
-
- on|off axes
- Turn the coordinate axes (really a mark on the origin) ON or OFF.
- E.g. off axes
-
- on|off outlines
- Set showing the map outlines on or off, press a key to continue
- after viewing the outlines.
- E.g. on outlines
-
- settings
- Show a list of the current origin, screen origin, range, scale, number
- of maps and whether the axes and outlines are on or off.
- E.g. settings
-
- findmap
- Allows the user to enter three initial coordinates and three image
- coordinates and calculates the map for those values.
- E.g. findmap
-
- make
- Puts the most recent values from findmap on the stack in order
- for set. The user needs to add the probability and map number
- before calling set.
- E.g. make .333 1 set
-
- <a> <b> <c> <d> <e> <f> <p> <n> set
- Sets the parameters for a map. The letters a-f correspond to the
- values for the matrix and offset vector, <p> is the probability for
- the map and <n> is the map number. All values except <n> are to
- be floating point numbers.
- E.g. 0.5 -0.5 0.5 0.5 0.0 0.0 0.5 1 set
-
- <m1> <m2> copy
- Copy map number <m1> to <m2> without disturbing <m1>.
- E.g. 2 5 copy
-
- <m> delete
- Delete map number <m> and move any other maps up in memory.
- E.g. 3 delete
- <m> insert
- Insert a blank map before map <m>.
- E.g. 1 insert
-
- cls
- Clear the window.
- E.g. cls
-
- bye
- Exit Fractal Lab Kit.
- E.g. bye
-
-
-
- Using the FindMap command : an example
-
- The FindMap command is perhaps the most useful command. It allows the
- user to find the parameters for a map by entering the coordinates and
- where they map to. This example will use the FindMap command to calculate
- the maps to find the Mandelbrot dragon which was introduced above.
-
- With in the program enter findmap. You will see be asked to enter the
- coordinates of three points from the original map. The origin, the lower
- right and upper left corners of the initial box (remember, it goes from
- 0..1 in both x and y) make good starting places. Therefore, enter 0 for
- x1 and 0 for y1, (1,0) for (x2,y2), and (0,1) for (x3,y3). You do not
- need to enter a decimal point with each number in this case, you can also
- press return to use the previously set value if desired (though it is not
- shown). For the image points, enter (x1',y1') as (0,0), (x2',y2') as
- (0.5,0.5) and (x3',y3') as (-0.5,0.5). The program will calculate the
- appropriate map and display its values. At the prompt, enter make 0.5 1
- set to make this newly calculated map the first map. Enter findmap again
- and press return for each of the original points since we will use the
- same ones as before. For the image points enter (x1',y1') as (1,0),
- (x2',y2') as (0.5,0.5) and (x3',y3') as (0.5,-0.5). Then enter make 0.5 2
- set to fix this as the second map. Lastly, enter 2 maps 120 220 screen
- cdraw to use two maps, adjust the screen origin so the image will fit, and
- draw using color.
-
-
-
-
- Advanced Features
-
-
- A very (very) brief introduction to programming in Forth
-
-
- Forth is an interpreted, stack based programming language known for its
- speed and extensibility. This is not an attempt to completely teach Forth
- so much as to teach a little about Forth so that the user who is
- unfamiliar with Forth can make some use of the language.
- Forth is a stack based language, data is manipulated using a stack that
- works in a way very similar to the lunch trays in a cafeteria. The last
- tray in the stack is the first one out. Because of this, all mathematical
- operations are in postfix format, i.e., instead of typing 4 + 7 one would
- type 4 7 + which would leave the value 11 on the top of the stack. This
- illustrates an important thing to remember about using Forth, anything
- that is entered is interpreted as either a word in the dictionary (more on
- that later) or a number to be pushed on the stack, so entering 4 7 + told
- Forth to push a 4 on the stack followed by a 7 and the + word adds the top
- two stack items. To see the value stored on the top of the stack use the
- . word. Note that this is a destructive operation, it prints the value at
- the top of the stack and removes it from the stack as well. To see the
- top stack value but NOT remove it you need to enter dup . to first
- duplicate the top item and then print it. By default, Forth only operates
- on 16-bit integers but Pocket Forth supports real numbers as well. Forth
- will interpret a value as a real number ONLY if it contains a decimal
- point! It is therefore important to enter a decimal point for every
- number that should be a real number and to NOT use one on numbers that
- should be integers.
- Forth supports the standard arithmetic operations: +, -, *, / (integers)
- and f+, f-, f*, f/ (real numbers). Use f. to print the top of stack as a
- real number. fdup duplicates the real number at the top of the stack
- while fswap will switch the top two real numbers on the stack. These few
- words will allow for using Forth as a simple calculator. Forth does not
- support higher mathematical functions.
- Forth derives its extensibility from the way in which programs are
- written. As Forth interprets tokens from the input line (anything
- surrounded by spaces is a token) it either pushes it on the stack as a
- number or looks it up as a word in its dictionary. A Forth program,
- therefore, consists of adding definitions to the dictionary. Definitions
- are begin with the : word and end with a semi-colon. Once defined, the
- word can be used in subsequent definitions. Parameters are passed via the
- stack. Forth does allow for the use of variables and constants, though
- these are slower than the stack. Use the word variable (or fvariable)
- followed by the name for the variable to create one. Use <value> constant
- ( or fconstant) <name> do define a constant. Examples: typing fvariable
- stddev will create room in the dictionary for a floating point variable
- named stddev while typing 3.141592 fconstant PI will create a constant for
- pi. Constants are really special words that push the value on the stack
- so that typing pi will cause the value to be pushed on the stack.
- However, entering the name of a variable will NOT place its value on the
- stack, but rather, the address where the variable is stored will be placed
- on the stack. To get the value of a variable a two word combination must
- be used: stddev f@ will 'fetch' a floating point number stored at the
- address that stddev places on the stack. Similarly, the value of an
- integer variable is found using @ instead of f@. To store a value in a
- variable, use ! or f! : 3 age ! or 1.414 sqr2 f!.
- Forth uses several standard control structures: if else then, do loop
- (or +loop), begin until, begin while repeat. The phrase
-
- count @ 100 < if ." Yes, there is room" cr
- else ." No, there is no room." cr then
-
- will check whether the current value of count is less than 100 or not.
- Forth supports <, >, = for comparing integer values. Pocket Forth has a
- single word for comparing floating point numbers, fcompare, which returns
- a -1 if f1<f2, 0 is f1=f2, and +1 if f1>f2, where f1 and f2 are the top
- two stack numbers (assumed to be floating point). It is important to note
- that unlike most other Forth words, fcompare does not remove the top two
- floating point numbers.
- The do loop is similar to the for loops in other languages. As might be
- expected, the syntax is <hi> <lo> do <body> loop where the index (pushed
- on the stack by the word r) will go from <lo> to <hi>-1. A variation is
- to use +loop instead of loop to jump by the value on the top of the stack
- (which must be positive). Begin until and begin while repeat are for
- bottom tested and top tested conditional loops. The condition is the same
- as for the if statement:
-
- 0 begin ." Hello" cr 1+ dup 100 < until
-
- will print the word 'Hello' 100 times. Similarly, this fragment will also
- print 'Hello' 100 times:
-
- 0 begin dup 99 < while ." Hello" cr 1+ repeat
-
-
- Putting it all together
-
- The following examples will illustrate the creation of simple Forth
- words, after which an example using fractal generating words will be
- presented.
-
- 1. Averaging four numbers
-
- : ave4 ( a b c d -- average ) + + + 4 / ;
-
- Using integer arithmetic, sum the top four stack items and divide the
- result by 4. Illustrates comments which are anything surrounded by (),
- note the space after the (. The comment given is known as a stack effect
- comment and shows what effect the word has on the stack. Initial stack
- items are on the left of the -- and the result is on the right.
-
- 2. Averaging N floating point numbers
-
- : averageN ( a1. ... aN. N -- average. )
- dup >r ( save N on the return stack )
- 1- 0 do ( adjust N and add the values )
- f+ loop
- r> ( get N off the return stack )
- 0 d>f f/ ; ( make it real and divide to find average )
-
- This example illustrates use of the return stack. The return stack is the
- place where Forth places addresses to return to when the current word is
- done executing. While a word is executing it is possible to use the
- return stack for temporary storage, but one must be careful to make sure
- that all values placed on the stack by >r are removed using r> before the
- word is done, otherwise Forth will attempt to return to ??? and very
- likely crash. The way to convert an integer to a real number is to use
- the words 0 d>f. This transforms the integer into a double length integer
- and then into a real number.
-
- 3. Evaluating a function: Y = 3.4 * EXP (X^2)
-
- fvariable x
- : sqr ( x. -- x.*x. ) fdup f* ;
- : cube ( x. -- x.^3 ) fdup fdup f* f* ;
- : expf ( x. -- exp[x.] ) ( use Taylor series approx. )
- fdup x f! 1.0 f+ x f@ sqr 2.0 f/ f+ x f@ cube 6.0 f/ f+ ;
- : Y ( x. -- Y[x.] ) expf 3.4 f* ;
-
- This is an example of factoring: the code for the square and cube could
- easily have been left in the definition of expf but factoring them out
- made the definition shorter and easier to read. In theory, according to
- some, a properly factored Forth program, combined with well chosen word
- names and stack effect comment, should be nearly self-documenting.
- These examples are brief, but hopefully should be sufficient, especially
- when combined with a list of Forth words, to allow writing of simple words
- to extend the power of the program.
-
-
- The Sierpinski Triangle : an example
-
-
- The Sierpinski Triangle is a commonly seen fractal consisting of a
- triangle that is made up of triangles. This will serve as an example of
- how the program can be extended by adding words to the Forth dictionary.
- The triangle is made up of three maps that divide the region 0..1 in x and
- 0..1 in y into three equal squares. We will develop a Forth word that
- will find the maps for the triangle and then generate the fractal.
- First, we must determine the maps. The findmap command's interactive
- nature is unsuited to our task, fortunately, there are three 'primitive'
- (i.e. non-interactive) words that will perform the same task: initial,
- image, and solve. These words operate as follows:
-
- <x1> <y1> <x2> <y2> <x3> <y3> initial
- Sets the initial points for finding a map, (x1,y1),(x2,y2),(x3,y3).
-
- <X1> <Y1> <X2> <Y2> <X3> <Y3> image
- Sets the image points for finding a map, (X1,Y1),(X2,Y2),(X3,Y3).
-
- solve
- Finds the values that will map the initial points to the image points.
-
- These words, when combined with make and set, will allow us to create a
- single Forth word to find all three maps at once. At this point, then, we
- can write:
-
- : sierpinski ( generates the Sierpinski Triangle)
- ( Set up initial values, for all maps )
- 0.0 0.0 1.0 0.0 0.0 1.0 initial
- ( First map )
- 0.0 0.0 0.5 0.0 0.0 0.5 image solve
- make 0.333 1 set
- ( Second map )
- 0.5 0.0 1.0 0.0 0.5 0.5 image solve
- make 0.333 2 set
- ( Third map )
- 0.25 0.5 0.75 0.5 0.25 1.0 image solve
- make 0.333 3 set
-
- Now before viewing the fractal show the maps, reset the program and show
- the settings, and draw the outlines:
-
- ( Show the maps )
- page ." The Sierpinski maps: " cr showmaps
- reset settings
- key drop ( wait for a key press )
- ( Show outlines when drawing )
- on outlines
- ( Reset the program and draw the fractal )
- cdraw ;
-
-
- Try this word and see what happens.
-
-
-
-
-
-
- Basic Forth words
-
- Below is a list of some basic Forth words and their use. With these it
- should be possible to define your own words for use with the program.
-
- Word Use
- swap ( a b -- b a ) Switch top two stack items
- dup ( a -- a a ) Duplicate top of stack
- over ( a b -- a b a ) Bring 2nd to top
- rot ( a b c -- b c a ) Rotate stack items
- variable ( -- ) Make a variable of next token
- constant ( a -- ) Make a constant of next token
- +, -, *, / ( a b -- a$b ) Math, where $ is an operation
- mod ( a b -- a mod b ) Remainder after dividing
- drop ( a -- ) Drop the top stack item
- cr ( -- ) Print a return character
- space ( -- ) Print a space (ASCII 32)
- emit ( a -- ) Print the character whose code
- is on the stack
- ." ( -- ) Print text until a " found
- . ( a -- ) Print the top of stack
- key ( -- a ) Get a key, ASCII code on stack
- bye ( -- ) Exit from Forth
- open ( -- ) Load a file from disk
- ?terminal ( -- b ) Has a key been pressed?
- ( ( -- ) Start a comment (remember space)
- !pen ( x y -- ) Move the pen to (x,y) (pixels)
- -to ( x y -- ) Line from current to (x,y)
- page ( -- ) Clear the screen
- --> ( -- ) Load filename, no spaces!
- open ( -- ) Load file chosen in Mac dialog
- ?button ( -- t ) Mouse button down?
- @mouse ( -- x y ) Push mouse position on stack
- save ( -- ) Save the current dictionary. This is PERMANANT!
- Only use a copy! Once saved, the words you defined will be available
- immediately when the program is next run.
-
- See the reference section for more words that are program specific. Words
- in plain text are special to Pocket Forth and may not be available on
- other Forth systems, though there will likely be something like them.
- Those interested in seriously learning Forth (some swear that it is the
- best computer language there is) should get a hold of the book Starting
- Forth by Leo Brodie (2nd ed. 1987), it is an excellent introduction.
-
- Reference
-
-
- Commands
-
- draw
- Draw a fractal based on the current maps. Press a key to stop.
- E.g. green color fern draw
-
- cdraw
- Except for plotting each map in a different color, it is the same as
- draw.
- E.g. spiral cdraw
-
- <n> idraw or <n> icdraw
- Same as draw and cdraw respectively except for iterating through
- <n>*500 points. Useful for drawing a fractal and stopping without
- user interaction.
-
- <n> edit
- Edit the n-th map. Enter a new value or press return to leave the
- existing value as is.
- E.g. 2 edit
- a = 0.5 ?-0.5 (new value)
- b = -0.5 ?<return> etc.
-
- zero-maps
- Erase all twelve maps.
- E.g. zero-maps
-
- <color.name> color
- Set the current drawing color to the color named. Valid colors are
- black, wite, red, green, blue, yellow, cyan, magenta
- E.g. magenta color
-
- <n> maps
- Set the number of maps to use to <n>.
- E.g. 4 maps
-
-
- <x> <y> origin
- Set the origin to (x,y). X and Y are floating point numbers.
- E.g. -0.354 .789 origin
-
- <u> <v> screen
- Set the screen origin to (u,v) (pixels).
- E.g. 120 220 screen
-
- <r> range
- Set the range to <r> (floating point). The viewing window is a
- square with the lower left corner as the origin and side length
- as range.
- E.g. 0.5 range
-
- <x> <y> scale
- Set the x-axis and y-axis scales to the floating point values given.
- The default scale is 1.0 for a full screen image. Changing the scale
- to a value less than one shrinks the image, greater than one expands
- the image.
- E.g. 2.0 2.0 scale
-
- mouse
- When issued, mouse will translate the position of the pointer into
- an x,y coordinate allowing the user to 'see' where certain parts of
- the image are. Clicking the mouse button between two points will
- measure the distance between them. Press a key to exit.
-
- on|off clear
- Turn clearing of page before drawing on and off. Default is on.
-
- on|off axes
- Turn the coordinate axes (really a mark on the origin) ON or OFF.
- E.g. off axes
-
- on|off outlines
- Set showing the map outlines on or off, press a key to continue
- after viewing the outlines.
- E.g. on outlines
-
-
- settings
- Show a list of the current origin, screen origin, range, scale, number
- of maps and whether the axes and outlines are on or off.
- E.g. settings
-
- findmap
- Allows the user to enter three initial coordinates and three image
- coordinates and calculates the map for those values.
- E.g. findmap
-
- make
- Puts the most recent values from findmap on the stack in order
- for set. The user needs to add the probability and map number
- before calling set.
- E.g. make .333 1 set
-
- <a> <b> <c> <d> <e> <f> <p> <n> set
- Sets the parameters for a map. The letters a-f correspond to the
- values for the matrix and offset vector, <p> is the probability for
- the map and <n> is the map number. All values except <n> are to
- be floating point numbers.
- E.g. 0.5 -0.5 0.5 0.5 0.0 0.0 0.5 1 set
-
- <m1> <m2> copy
- Copy map number <m1> to <m2> without disturbing <m1>.
- E.g. 2 5 copy
-
- <m> delete
- Delete map number <m> and move any other maps up in memory.
- E.g. 3 delete
-
- <m> insert
- Insert a blank map before map <m>.
- E.g. 1 insert
-
- cls
- Clear the window.
- E.g. cls
-
-
- bye
- Exit Fractal Lab Kit.
- E.g. bye
-
-
- <9|12|13> monitor
- Set the program for a 9, 12, or 13 inch monitor.
- E.g. 13 monitor
-
- mem
- Show the available dictionary space. (Forth only has 32k)
- E.g. mem
-
- ?origin, ?screen, ?scale, ?range, ?maps, ?axes, ?outline, ?clear
- Show individual settings. settings calls each of these.
-
- <n> show
- Show the values of map <n>.
- E.g. 3 show
-
-
-
- Primitive commands
-
- These commands (words) are 'primitive' in the sense that they are called
- by the regular command words. Since they are standard Forth words they
- are available for user use as well.
-
-
- input ( -- a )
- Get a 16-bit integer on the stack.
-
- finput ( -- f b )
- Get a floating point number on the stack and a boolean value that is
- true if the user pressed the return key only, in which case the
- number is 0.0.
-
- #map->addr ( a -- addr )
- Convert a number for a map into an address to the map location in
- memory.
-
- get ( offset map# -- value )
- Get a value for a particular map. The offset is a branch into the
- map, each value is 10 bytes long. The constants a,b,c,d,e,f and p
- are defined to give the proper offset: c 3 get returns the c value
- of the third map.
-
- update ( value offset map# -- )
- Put the value in the numbered map at the offset (use a-f or p).
-
- print ( addr -- )
- Print the map starting at addr.
-
- wsize ( h v -- )
- Resize the window to h pixels high and v pixels across.
-
- rand ( -- f )
- Put a random floating point number from 0..1 on the stack.
-
- dot ( u v -- )
- Draw a dot on the screen at (u,v) (pixels).
-
- plot ( x. y. -- )
- Plot the point (x,y) on the screen.
-
- plotto ( x. y. -- )
- Draw a line from the last plotted point to (x,y).
-
- determinant ( -- d )
- Find the determinant of the 3x3 matrix whose values are stored
- in the floating point variables d1 through d9. Values in the form:
- [ [d1,d2,d3],[d4,d5,d6].[d7,d8,d9]].
-
- x->d ( -- )
- Copy the values in x1,y1 .. x3,y3 to the matrix d. Used to setup for
- finding a map.
-
- xy->uv ( x. y. -- u v )
- Change real coordinates (x,y) into screen coordinates (u,v). Call
- factor first.
-
- factor ( -- )
- Calculates redundant factors for xy->uv to speed drawing.
-
- firstpoints ( -- )
- Get the initial points for a map, interactive.
-
- solve3x3 ( -- f. d. c. e. b. a. )
- Solve for a map, calculated values on stack. Call either firstpoints
- and imagepoints or initial and image before calling solve3x3.
-
- outputmap ( f. d. c. e. b. a. -- )
- Display map values on the stack on the screen.
-